package chapter14;

import java.io.*;
import java.util.zip.*;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2019/2/21 18:03
 */
public class ZipTest {
    // 空目录使用/
    private static final String EMPTY_FORDER_SEPARATOR = "/";

    public static void main(String[] args) throws Exception {
        String fileName = "D:\\hello.txt";
//        gzip(fileName);

        /*String zipName = "D:\\hello.txt.gz";
        String unzipName = "D:\\hello1.txt";
        gunzip(zipName, unzipName);*/

        System.out.println(File.separator);
        System.out.println(File.pathSeparator);

        String inFile = "D:\\test";
        String outFile = "D:\\test.zip";
        zip(inFile);

    }

    public static void unzip(String zipFile, String destDir) {
        File zin = new File(zipFile);

        if (zin.exists()) {
            zin.delete();
        }

        if (!destDir.endsWith(File.separator)) {
            destDir += File.separator;
        }
        try (ZipInputStream inputStream = new ZipInputStream(new BufferedInputStream(new FileInputStream(zin)))) {
            ZipEntry entry;
            while ((entry = inputStream.getNextEntry()) != null) {
                extractZipEntry(entry, inputStream, destDir);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void extractZipEntry(ZipEntry zipEntry, ZipInputStream inputStream, String desDir) {
        if (!zipEntry.isDirectory()) {
            File parent = new File(desDir + zipEntry.getName()).getParentFile();
            if (!parent.exists()) {
                parent.mkdirs();
            }

            try (OutputStream entryOut = new BufferedOutputStream(new FileOutputStream(desDir + zipEntry.getName()))) {
                copy(inputStream, entryOut);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            new File(desDir + zipEntry.getName()).mkdirs();
        }
    }

    /**
     * 可以压缩文件夹或者文件
     */
    private static void zip(String fileName) {
        String zipFileName = fileName + ".zip";
        File infile = new File(fileName);
        try (ZipOutputStream outputStream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFileName)))) {
            if (!infile.exists()) {
                throw new FileNotFoundException(infile.getCanonicalPath());
            }
            infile = infile.getCanonicalFile();
            String rootPath = infile.getParent();
            if (!rootPath.endsWith(File.separator)) {
                rootPath += File.separator;
            }
            addFileToZipOut(infile, outputStream, rootPath);

            System.out.println("压缩完成...");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void addFileToZipOut(File file, ZipOutputStream outputStream, String rootPath) throws IOException {
        String relativePath = file.getCanonicalPath().substring(rootPath.length());
        if (file.isFile()) {
            outputStream.putNextEntry(new ZipEntry(relativePath));
            try (InputStream inputStream = new BufferedInputStream(new FileInputStream(file))) {
                System.out.println("添加到压缩文件" + file.getCanonicalPath());
                copy(inputStream, outputStream);
            }
        } else {
            File[] files = file.listFiles();
            // 注意：在压缩空文件夹的时候必须使用‘/’作为文件目录分隔符进行结尾
            if (files.length == 0) {
                String dirPath = relativePath + EMPTY_FORDER_SEPARATOR;
                System.out.println("创建空的压缩目录" + dirPath);
                outputStream.putNextEntry(new ZipEntry(dirPath));
            } else {
                for (File f : file.listFiles()) {
                    addFileToZipOut(f, outputStream, rootPath);
                }
            }
        }
    }

    private static void gunzip(String fileName, String unzipFileName) {
        try (InputStream inputStream = new GZIPInputStream(new BufferedInputStream(new FileInputStream(fileName)));
             OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(unzipFileName))
        ) {
            copy(inputStream, outputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void gzip(String fileName) {
        String gzipFileName = fileName + ".gz";
        try (InputStream inputStream = new BufferedInputStream(new FileInputStream(fileName));
             OutputStream outputStream = new GZIPOutputStream(new BufferedOutputStream(new FileOutputStream(gzipFileName)))
        ) {
            copy(inputStream, outputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void copy(InputStream in, OutputStream out) throws IOException {
        int numRead = 0;
        byte[] buffer = new byte[1024];
        while ((numRead = in.read(buffer)) != -1) {
            out.write(buffer, 0, numRead);
        }
    }
}
